<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>数字最短滚动</title>
    <link rel="stylesheet" href="./style.css" />
    <!-- <link rel="stylesheet" href="../common/normalize.css" /> -->
  </head>

  <body>
    <button class="button">数字滚动</button>
    <p><b>获取到的数字：</b><span>0000</span></p>
    <div class="num-container">
      <div class="scroller-window">
        <div class="single-scroller">
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
        </div>
      </div>
      <div class="scroller-window">
        <div class="single-scroller">
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
        </div>
      </div>
      <div class="scroller-window">
        <div class="single-scroller">
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
        </div>
      </div>
      <div class="scroller-window">
        <div class="single-scroller">
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
          <p>5</p>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
          <p>0</p>
          <p>1</p>
          <p>2</p>
          <p>3</p>
          <p>4</p>
        </div>
      </div>
    </div>
  </body>
  <script>
    //获取随机数
    function genRandomNum() {
      // Math.floor()向下取整
      return Math.floor(Math.random() * 10); //Math.random()产生一个[0，1)之间的随机数
    }
    //获取与传入数字不同的随机数
    function diffRandomNum(num) {
      const num1 = genRandomNum(); //生成随机数num
      if (num === num1) {
        diffRandomNum(num);
      } else {
        return num1;
      }
    }
    // 计算y轴最快过渡距离
    function getFastestTranslation(start, end) {
      let direction = 1; // -1 -> scroll up | 1 -> scroll down
      let steps = 0;
      let startTansition = getNormalTranslation(start);
      // console.log(start, end, 11);
      if (start > end) {
        // start - end 为 start 向 end 递减的次数
        setDirectionAndSteps(Math.abs(start - end), Math.abs(10 - start + end));
      } else if (start < end) {
        // end - start 为 start 向 end 递减的次数
        setDirectionAndSteps(Math.abs(10 - end + start), Math.abs(end - start));
      }

      startTansition += direction * steps * step;

      /**
       * 比较上下方向，设置最短步数
       * @param {*} dstep 向下滚动的步数
       * @param {*} ustep 向上滚动的步数
       */
      // 判断滚动最短距离是向下还是向上
      // direction:滚轮移动方向 -1👆  1👇
      // step：单个数字所占的所有数字高度的分数
      // steps：移动的步数
      function setDirectionAndSteps(dstep, ustep) {
        const isUpperFaster = dstep > ustep;
        direction = isUpperFaster ? -1 : 1;
        steps = isUpperFaster ? ustep : dstep;
      }

      return `translateY(${startTansition}%)`;
    }
    // 中间区域过渡距离
    function getNormalTranslation(num) {
      // 每个 p 元素占比为100/20=5%, 第一个 0 在 25% 处出现
      return -(25 + num * 5); //此处为负数原因是要scroller向上滚动，数字向下滚动
    }
    // 复位函数
    // 如果滚轮落在了上半区或下半区，那么下一次滚动可能会不正常
    // 因此每次超出中间区就执行一次没有过渡的 translateY 将滚轮恢复到中间区
    function reposition({ style }, num) {
      const { transitionDuration } = style;
      const normalTranslation = `translateY(${getNormalTranslation(num)}%)`;
      // 判断移动的距离是否在中间区域内
      if (style.transform !== normalTranslation) {
        style.transitionDuration = "0s";
        // 直接变换到与移动距离相同的中间区域
        style.transform = normalTranslation;
        // requestAnimationFrame(
        //   requestAnimationFrame.bind(null, () => {
        setTimeout(() => {
          //在transiion里面，当连续两个duration的属性设置紧挨着时，会默认以最后一个duration属性为值,可以采用定时器的方式解决。
          style.transitionDuration = transitionDuration;
        }, 0);
        //   })
        // );
      }
    }

    const button = document.getElementsByClassName("button")[0];
    const allNum = document.querySelector("p>span");
    let scrollerList = document.getElementsByClassName("single-scroller");
    scrollerList=Array.from(scrollerList)
    let step = 5; //scroller里20个数字，每个占 100/20=5%
    scrollerList.forEach(scroller=>{
      scroller.start = 0;
      scroller.style.transform = `translateY(${getNormalTranslation(scroller.start)}%)`;
    })
    button.onclick = () => {
      allNum.innerHTML=""
      scrollerList.forEach(scroller=>{
        scroller.start = 0;
        scroller.end = genRandomNum();
        scroller.style.transform = `translateY(${getNormalTranslation(scroller.start)}%)`;
        scroller.end = genRandomNum();
        if (scroller.end === scroller.start) {
          scroller.end = diffRandomNum(scroller.end);
        }
        allNum.innerHTML+=scroller.end
        console.log(scroller.start, scroller.end, "se");
        scroller.style.transform = getFastestTranslation(scroller.start, scroller.end);
        scroller.start = scroller.end;
        //transitionend 该事件在 CSS 完成过渡后触发。
        scroller.addEventListener("transitionend", ({ target }) => {
          reposition(target, scroller.end);
        });
      })
    };
  </script>
</html>
